using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Soft1ApiDemo.Domain.Entity;
using Soft1ApiDemo.Domain.Repository;
using Soft1ApiDemo.Infrastructure.Utils;

namespace Soft1ApiDemo.Infrastructure.Filters
{
    public class AuditLogFilter : IAsyncActionFilter
    {
        private readonly IRepository<AuditLog> _auditLogRes;

        public AuditLogFilter(IRepository<AuditLog> auditLogRes)
        {
            _auditLogRes = auditLogRes;
        }

        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            // 判断是否写日志
            // if (!ShouldSaveAudit(context))
            // {
            //     await next();
            //     return;
            // }

            //接口Type
            var type = (context.ActionDescriptor as ControllerActionDescriptor).ControllerTypeInfo.AsType();
            //方法信息
            var method = (context.ActionDescriptor as ControllerActionDescriptor).MethodInfo;
            //方法参数
            var arguments = context.ActionArguments;
            //开始计时
            var stopwatch = Stopwatch.StartNew();
            var auditInfo = new AuditLog
            {
                UserInfo = "佚名",
                ServiceName = type != null ? type.FullName : "",
                MethodName = method.Name,
                ////请求参数转Json
                Parameters = JsonHelper.JsonSerialize(arguments),
                ExecutionTime = DateTime.Now,
                BrowserInfo = context.HttpContext.Request.Headers["User-Agent"].ToString(),
                ClientIpAddress = context.HttpContext.Connection.RemoteIpAddress.ToString(),
                //ClientName = _clientInfoProvider.ComputerName.TruncateWithPostfix(EntityDefault.FieldsLength100),
            };

            ActionExecutedContext result = null;
            try
            {
                result = await next();
                if (result.Exception != null && !result.ExceptionHandled)
                {
                    auditInfo.Exception = result.Exception.ToString();
                }
            }
            catch (Exception ex)
            {
                auditInfo.Exception = ex.ToString();
                throw;
            }
            finally
            {
                stopwatch.Stop();
                auditInfo.ExecutionDuration = Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds);

                if (result != null)
                {
                    switch (result.Result)
                    {
                        case ObjectResult objectResult:
                            auditInfo.ReturnValue = JsonHelper.JsonSerialize(objectResult.Value);
                            break;

                        case JsonResult jsonResult:
                            auditInfo.ReturnValue = JsonHelper.JsonSerialize(jsonResult.Value);
                            break;

                        case ContentResult contentResult:
                            auditInfo.ReturnValue = contentResult.Content;
                            break;
                    }
                }
                Console.WriteLine(auditInfo.ToString());
                //保存审计日志
                _auditLogRes.Add(auditInfo);
            }
        }
    }
}